package org.unicen.exa.io.worker.assigner.algorithm;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.unicen.exa.io.worker.assigner.core.model.Job;
import org.unicen.exa.io.worker.assigner.core.model.JobWorking;
import org.unicen.exa.io.worker.assigner.core.model.Worker;
import org.unicen.exa.io.worker.assigner.core.state.StatesConstants;
import org.unicen.exa.io.worker.assigner.dao.JobDao;
import org.unicen.exa.io.worker.assigner.dao.JobWorkingDao;
import org.unicen.exa.io.worker.assigner.dao.WorkerDao;

@Component
public class Assigner implements Runnable {

	private Logger logger = Logger.getLogger(Assigner.class);

	private @Autowired JobWorkingDao<JobWorking> jobWorkingDao;
	private @Autowired JobDao<Job> jobDao;
	private @Autowired WorkerDao<Worker> workerDao;
	private int timeInSecond;

//	public Assigner(String str, WorkerDao<Worker> workerDao, JobWorkingDao<JobWorking> jobWorkingDao, JobDao<Job> jobDao, int timeInSecond) {
//		this.timeInSecond = timeInSecond;
//		this.jobDao = jobDao;
//		this.workerDao = workerDao;
//		this.jobWorkingDao = jobWorkingDao;
//
//	}
	
	@Value("#{appProperties.timeInSecond}")
	public void setTimeInSecond(int timeInSecond) {
		this.timeInSecond = timeInSecond;
	}

	public void run() {
		while (true) {
			logger.debug(String.format("RETRIEVING jobs to assigns"));
			try {
				for (Job job : jobDao.gets()) {
					if (job.getState().equals(StatesConstants.JOB_STATE_PENDING)){
						for (Worker worker : workerDao.gets()) {
							float weight = worker.getMaxWeight() - (worker.getWeight() + job.getWeight());
							if (worker.getState().equals(StatesConstants.WORKER_INSTANCES_WORKING)&&  weight > 0){
								logger.debug(String.format("ASSIGN job with id = %s to worker with id = %s", job.getId().toString(), worker.getId().toString()));
								JobWorking jobWorking = new JobWorking();
								jobWorking.setId(job.getId());
								jobWorking.setJobId(job.getId());
								jobWorking.setWorkerId(worker.getId());
								jobWorking.setStatus(StatesConstants.JOB_WORKING_ASSIGN);
								jobWorkingDao.post(job.getId(), jobWorking);
								job.setState(StatesConstants.JOB_STATE_ASSIGN);
								jobDao.put(job);
								worker.setWeight(worker.getWeight() + job.getWeight());
								workerDao.put(worker);
							}
						}
					}
				}
				Thread.sleep(timeInSecond*1000);
			} catch (InterruptedException e) {
				logger.error(e);

			}
		}
	}

}
